package org.richin.reflection.util;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.richin.exception.BeansException;
import org.richin.lang.util.ClassUtil;
import org.richin.lang.util.StringUtils;
import org.richin.system.util.Assert;
import org.springframework.util.ReflectionUtils;

public class BeanUtils {
	private static final Log log=LogFactory.getLog(BeanUtils.class) ;
	/**
	 * 将bean属性以及值以Map形式返回,并且返回的Map保持Bean原有的属性类型
	 * 
	 * @param bean 要转换为MAP的JavaBean实例
	 * @return 以bean的字段名为key,字段值为value的Map对象
	 * @throws Exception
	 */
	public static Map describe(Object bean)throws Exception{
		Map result=new HashMap();
		Field[] fields=ClassUtil.getFields(bean.getClass(), 0);
		for(int i=0;i<fields.length;i++){
			String propertyName=fields[i].getName();
			result.put(propertyName, ReflectUtils.getFieldValue(bean, propertyName));
		}
		
		return result;
	}
	/**
	   * 调用org.apache.commons.beanutils.BeanUtils
	   * 的方法 copyProperties（)
	   * @param dest 目标对象
	   * @param orig 初始对象
	   * @pdOid 5e48bdac-0e1f-40c3-8fca-6ca66e1417fc
	   */
	  public static void copyProperties(Object dest, Object orig) {
	    try {
	      org.apache.commons.beanutils.BeanUtils.copyProperties(dest, orig);
	    }
	    catch (Exception e) {
	      e.printStackTrace();
	    }
	  }
	  /**
	     * 循环向上转型,获取对象的DeclaredField.
	     *
	     * @param object 对象实例
	     * @param propertyName 属性名
	     * @return 返回对应的Field
	     * @throws NoSuchFieldException 如果没有该Field时抛出
	     */
	    public static Field getDeclaredField(Object object, String propertyName)
	        throws NoSuchFieldException {
	        Assert.notNull(object);
	        Assert.hasText(propertyName);

	        return getDeclaredField(object.getClass(), propertyName);
	    }

	    /**
	     * 循环向上转型,获取对象的DeclaredField.
	     *
	     * @param clazz 类型
	     * @param propertyName 属性名
	     * @return 返回对应的Field
	     * @throws NoSuchFieldException 如果没有该Field时抛出.
	     */
	    public static Field getDeclaredField(Class clazz, String propertyName)
	        throws NoSuchFieldException {
	        Assert.notNull(clazz);
	        Assert.hasText(propertyName);

	        for (Class superClass = clazz; superClass != Object.class;
	                superClass = superClass.getSuperclass()) {
	            try {
	                return superClass.getDeclaredField(propertyName);
	            } catch (NoSuchFieldException ex) {
	                // Field不在当前类定义,继续向上转型
	                System.err.println(ex);
	            }
	        }

	        throw new NoSuchFieldException("No such field: " + clazz.getName()
	            + '.' + propertyName);
	    }

	    /**
	     * 暴力获取对象变量值,忽略private,protected修饰符的限制.
	     *
	     * @param object 对象实例
	     * @param propertyName 属性名
	     * @return 强制获得属性值
	     * @throws NoSuchFieldException 如果没有该Field时抛出.
	     */
	    public static Object forceGetProperty(final Object object,
	        final String propertyName) throws NoSuchFieldException {
	        Assert.notNull(object);
	        Assert.hasText(propertyName);

	        final Field field = getDeclaredField(object, propertyName);

	        return AccessController.doPrivileged(new PrivilegedAction() {
	                /** * run. */
	                public Object run() {
	                    boolean accessible = field.isAccessible();
	                    field.setAccessible(true);

	                    Object result = null;

	                    try {
	                        result = field.get(object);
	                    } catch (IllegalAccessException e) {
	                        log.info("error wont' happen");
	                    }

	                    field.setAccessible(accessible);

	                    return result;
	                }
	            });
	    }

	    /**
	     * 暴力设置对象变量值,忽略private,protected修饰符的限制.
	     *
	     * @param object 对象实例
	     * @param propertyName 属性名
	     * @param newValue 赋予的属性值
	     * @throws NoSuchFieldException 如果没有该Field时抛出.
	     */
	    public static void forceSetProperty(final Object object,
	        final String propertyName, final Object newValue)
	        throws NoSuchFieldException {
	        Assert.notNull(object);
	        Assert.hasText(propertyName);

	        final Field field = getDeclaredField(object, propertyName);

	        AccessController.doPrivileged(new PrivilegedAction() {
	                /** * run. */
	                public Object run() {
	                    boolean accessible = field.isAccessible();
	                    field.setAccessible(true);

	                    try {
	                        field.set(object, newValue);
	                    } catch (IllegalAccessException e) {
	                        log.info("Error won't happen");
	                    }

	                    field.setAccessible(accessible);

	                    return null;
	                }
	            });
	    }

	    /**
	     * 暴力调用对象函数,忽略private,protected修饰符的限制.
	     *
	     * @param object 对象实例
	     * @param methodName 方法名
	     * @param params 方法参数
	     * @return Object 方法调用返回的结果对象
	     * @throws NoSuchMethodException 如果没有该Method时抛出.
	     */
	    public static Object invokePrivateMethod(final Object object,
	        final String methodName, final Object... params)
	        throws NoSuchMethodException {
	        Assert.notNull(object);
	        Assert.hasText(methodName);

	        Class[] types = new Class[params.length];

	        for (int i = 0; i < params.length; i++) {
	            types[i] = params[i].getClass();
	        }

	        Class clazz = object.getClass();
	        Method method = null;

	        for (Class superClass = clazz; superClass != Object.class;
	                superClass = superClass.getSuperclass()) {
	            try {
	                method = superClass.getDeclaredMethod(methodName, types);

	                break;
	            } catch (NoSuchMethodException ex) {
	                // 方法不在当前类定义,继续向上转型
	                System.err.println(ex);
	            }
	        }

	        if (method == null) {
	            throw new NoSuchMethodException("No Such Method:"
	                + clazz.getSimpleName() + methodName);
	        }

	        final Method m = method;

	        return AccessController.doPrivileged(new PrivilegedAction() {
	                /** * run. */
	                public Object run() {
	                    boolean accessible = m.isAccessible();
	                    m.setAccessible(true);

	                    Object result = null;

	                    try {
	                        result = m.invoke(object, params);
	                    } catch (Exception e) {
	                        ReflectionUtils.handleReflectionException(e);
	                    }

	                    m.setAccessible(accessible);

	                    return result;
	                }
	            });
	    }

	    /**
	     * 按Field的类型取得Field列表.
	     *
	     * @param object 对象实例
	     * @param type 类型
	     * @return 属性对象列表
	     */
	    public static List<Field> getFieldsByType(Object object, Class type) {
	        List<Field> list = new ArrayList<Field>();
	        Field[] fields = object.getClass().getDeclaredFields();

	        for (Field field : fields) {
	            if (field.getType().isAssignableFrom(type)) {
	                list.add(field);
	            }
	        }

	        return list;
	    }

	    /**
	     * 按FieldName获得Field的类型.
	     *
	     * @param type 类型
	     * @param name 属性名
	     * @return 属性的类型
	     * @throws NoSuchFieldException 指定属性不存在时，抛出异常
	     */
	    public static Class getPropertyType(Class type, String name)
	        throws NoSuchFieldException {
	        return getDeclaredField(type, name).getType();
	    }

	    /**
	     * 获得field的getter函数名称.
	     *
	     * @param type 类型
	     * @param fieldName 属性名
	     * @return getter方法名
	     * @throws NoSuchFieldException field不存在时抛出异常
	     */
	    public static String getGetterName(Class type, String fieldName)
	        throws NoSuchFieldException {
	        Assert.notNull(type, "Type required");
	        Assert.hasText(fieldName, "FieldName required");

	        Class fieldType = getDeclaredField(type, fieldName).getType();

	        if ((fieldType == boolean.class) || (fieldType == Boolean.class)) {
	            return "is" + StringUtils.capitalize(fieldName);
	        } else {
	            return "get" + StringUtils.capitalize(fieldName);
	        }
	    }

	    /**
	     * 获得field的getter函数,如果找不到该方法,返回null.
	     *
	     * @param type 类型
	     * @param fieldName 属性名
	     * @return getter方法对象
	     */
	    public static Method getGetterMethod(Class type, String fieldName) {
	        try {
	            return type.getMethod(getGetterName(type, fieldName));
	        } catch (NoSuchMethodException ex) {
	            log.error(ex.getMessage(), ex);
	        } catch (NoSuchFieldException ex) {
	            log.error(ex.getMessage(), ex);
	        }

	        return null;
	    }
		/**
		 *使用默认构造子初始化一个类实例
		 * @param　要实例化的类
		 * @return the new instance
		 */
		public static Object instantiateClass(Class clazz) throws BeansException {
			Assert.notNull(clazz, "指定的类名不能为null");
			if (clazz.isInterface()) {
				throw new BeansException("指定的class是一个接口，不能初始化!",clazz);
			}
			try {
				return instantiateClass(clazz.getDeclaredConstructor((Class[]) null), null);
			}
			catch (NoSuchMethodException ex) {
				throw new BeansException( "找不到默认构造函数!", ex,clazz);
			}
		}

		/**
		 *根据构造方法初始化一个类实例
		 * @param contor 构造函数
		 * @param args 构造子的参数
		 * @return 被创建的类实例
		 */
		public static Object instantiateClass(Constructor contor, Object[] args) throws BeansException {
			Assert.notNull(contor, "构造子不能为null");
			try {
				if (!Modifier.isPublic(contor.getModifiers()) ||
						!Modifier.isPublic(contor.getDeclaringClass().getModifiers())) {
					contor.setAccessible(true);
				}
				return contor.newInstance(args);
			}		
			catch (Exception ex) {
				throw new BeansException(
						"构造实例错误!", ex,contor.getDeclaringClass());
			}
		}
		
}
